﻿using System;
using System.Collections.Generic;

namespace Jayden.Dll.Core.Persistence.Models
{
	public class Model
	{
		private Configuration m_Configuration;

		public Model(Configuration config)
		{
			m_Configuration = config;
		}

		Dictionary<string, Namespace> m_Namespaces = new Dictionary<string, Namespace>();

		public Configuration Configuration { get { return m_Configuration; } }

		private Configuration GetNamepsaceConfiguration(string ns)
		{
			string xpath = string.Format("Namespace[@name=\"{0}\"]", ns);
			return m_Configuration.GetConfiguration(xpath);
		}
		private string[] GetNamespaces()
		{
			string xpath = "Namespace/@name";
			return m_Configuration.GetValues(xpath);
		}

		public Namespace GetNamspace(string ns)
		{
			Namespace nSpace = null;
			if (m_Namespaces.TryGetValue(ns, out nSpace))
				return nSpace;
			Configuration nsConfig = GetNamepsaceConfiguration(ns);
			if (nsConfig == null)
				throw new Exception(string.Format("Unknow Namespace: '{0}'.", ns));
			nSpace = new Namespace(this, ns, nsConfig);
			m_Namespaces.Add(ns, nSpace);
			return nSpace;
		}
		public Entity GetEntity(string ns, string en)
		{
			Namespace nameSpace = GetNamspace(ns);
			return nameSpace[en];
		}
		public Entity GetEntity(string fen)
		{
			int index = fen.LastIndexOf('.');
			if (index >= 0)
			{
				string en = fen.Substring(index + 1);
				string ns = fen.Substring(0, index);
				return GetEntity(ns, en);
			}
			return null;
		}
		public Property GetProperty(string ns, string en, string pn)
		{
			Entity entity = GetEntity(ns, en);
			return entity[pn];
		}

		public Entity FindEntity(string en)
		{
			List<Entity> entities = new List<Entity>();
			foreach (string ns in GetNamespaces())
			{
				Namespace nameSpace = GetNamspace(ns);
				if (nameSpace.HaveEntity(en))
					entities.Add(nameSpace[en]);
			}
			if (entities.Count == 0)
				return null;
			if (entities.Count == 1)
				return entities[0];
			throw new InvalidOperationException(string.Format("Multiple namespace contains entity '{0}' : '{1}'.", en, string.Join("', '", entities)));
		}
	}
}
